@file:Suppress("SimpleDateFormat", "CustomX509TrustManager")
package kotlinx.coroutines.script.tes

import org.json.JSONObject
import java.io.BufferedReader
import java.io.InputStream
import java.io.InputStreamReader
import java.io.OutputStream
import java.net.HttpURLConnection
import java.net.Proxy
import java.net.URL
import java.nio.charset.StandardCharsets
import java.security.cert.X509Certificate
import javax.net.ssl.HostnameVerifier
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager

object HttpRequest {
    private val hostnameVerifier = HostnameVerifier { _, _ -> true }
    private val sslSocketFactory: SSLSocketFactory? = try {
        val sslContext = SSLContext.getInstance("TLS")
        sslContext.init(null, arrayOf(object : X509TrustManager {
            override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unit
            override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unit
            override fun getAcceptedIssuers() = null
        }), null)
        sslContext.socketFactory
    } catch (ignore: Throwable) {
        null
    }

    
    fun invokeUrlApi(url: String): String? {
        var ins: InputStream? = null
        var inputStream: InputStreamReader? = null
        var reader: BufferedReader? = null
        try {
            val conn = URL(url).openConnection() as HttpURLConnection
            if (conn is HttpsURLConnection) {
                conn.hostnameVerifier = hostnameVerifier
                if (sslSocketFactory != null)
                    conn.sslSocketFactory = sslSocketFactory
            }
                conn.requestMethod = "GET"
                conn.useCaches = false
            conn.connectTimeout = 5000
            conn.readTimeout = 5000
            if (conn.responseCode == 200) {
                val connInputStream = conn.inputStream
                ins = connInputStream
                inputStream = InputStreamReader(connInputStream, StandardCharsets.UTF_8)
                reader = BufferedReader(inputStream)
                var line: String?
                val result = StringBuffer()
                while (reader.readLine().also { line = it } != null) {
                    result.append(line)
                }
                return result.toString().also {
                    printLog { "response: $it" }
                }   // {"apig":"mtop.common.getTimestamp","v":"*","ret":["SUCCESS::接口调用成功"],"data":{"t":"1618908520562"}}
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        } finally {
            reader?.closeQuietly()
            inputStream?.closeQuietly()
            ins?.closeQuietly()
        }
        return null
    }


    fun invokePost(url: String,
                   header: Map<String, String>,
                   params: Map<String, String>): String? {
        printLog { "POST $url\nheader:${header.entries.joinToString("&")}\nparams:${params.entries.joinToString("&")}" }
        var ins: InputStream? = null
        var inputStream: InputStreamReader? = null
        var outputStream: OutputStream? = null
        var reader: BufferedReader? = null
        try {
//            val conn = URL(url).openConnection(Proxy.NO_PROXY) as HttpURLConnection
            val conn = URL(url).openConnection() as HttpURLConnection
            if (conn is HttpsURLConnection) {
                conn.hostnameVerifier = hostnameVerifier
                if (sslSocketFactory != null)
                    conn.sslSocketFactory = sslSocketFactory
            }
            conn.requestMethod = "POST"
            conn.connectTimeout = 10000
            conn.readTimeout = 10000
            conn.doOutput = true
            // 添加请求头信息
            for ((key, value) in header) {
                conn.setRequestProperty(key, value)
            }
            // 将参数写入输出流
            val postData = JSONObject(params).toString()
            conn.setRequestProperty("Content-Type", "application/json")
            outputStream = conn.outputStream
            outputStream.write(postData.toByteArray(StandardCharsets.UTF_8))
            outputStream.flush()

            printLog { "invokePost connResponseCode ${conn.responseCode}" }
            if (conn.responseCode == 200) {
                val connInputStream = conn.inputStream
                ins = connInputStream
                inputStream = InputStreamReader(connInputStream, StandardCharsets.UTF_8)
                reader = BufferedReader(inputStream)
                var line: String?
                val result = StringBuffer()
                while (reader.readLine().also { line = it } != null) {
                    result.append(line)
                }
                return result.toString()
            }
        } catch (e: Throwable) {
            e.printStackTrace()
        } finally {
            reader?.closeQuietly()
            inputStream?.closeQuietly()
            outputStream?.closeQuietly()
            ins?.closeQuietly()
        }
        return null
    }

}